package com.lagou.module4hw.hw56.parsepackage;


import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.File;
import java.nio.ByteBuffer;
import java.util.Arrays;


/**
 * 自定义加包和解析包类
 */
public class ParsePack {

    /**
     * 给字符串加包
     * 第一位 0 - 普通字符串
     * 1 - 8 用于存储字符串的长度
     * @param str 需要发送的字符串
     * @return 返回加包后的字节数组
     */
    @NotNull
    public static byte[] pack(String str){
        //得到字符串的byte数组，把字符串转成byte类型
        byte[] strBytes = str.getBytes();

        //创建长度为9+strBytes.length长度的字节数组
        byte[] packBytes = new byte[9+strBytes.length];

        //packBytes 第一位为0，代表普通字符串
        packBytes[0] = 0;

        //申请8个长度的byte数组，把字符串的byte类型的数组长度写入申请的数组中
        byte[] sizeBytes = ByteBuffer.allocate(8).putLong(strBytes.length).array();

        //组装字符串长度  packBytes 第2到9位为str的字节数组的长度
        System.arraycopy(sizeBytes,0,packBytes,1,8);
        //组装字符串内容
        System.arraycopy(strBytes,0,packBytes,9,strBytes.length);

        return packBytes;
    }

    /**
     * 是否为字符串
     * @param bytes
     * @return true是字符串，false不是字符串
     */
    public static boolean isString(byte[] bytes){
        return bytes[0] == 0;
    }

    /**
     * 解析字符串
     * @param bytes
     * @return
     */
    public static String unpack(byte[] bytes){
        if( isString(bytes)){ //是字符串，按字符串加包的方式解析
            //下标位1到小标为8的8位代表字符串的长度
            long strByteSize = ByteBuffer.wrap(bytes,1,8).getLong();

            //下标为9开始一直取strByteSize长度的字节代表字符串的内容
            String str = new String(bytes,9, (int) strByteSize);
            return str;
        }
        return  null;
    }

    /**
     * 下标为0的位置  1 - 代表文件
     * 下标1~8   文件名大小 假设为i
     * 下标9~i  文件名
     * 下标i+1~i+8 文件大小
     */
    public static byte[] packFile(String filename){


        if (null == filename || !filename.startsWith("file:")) {
            return null;
        }
        // 不是文件，直接结束
        File file = new File(filename.substring(5));
        if (!file.isFile()) {
            return null;
        }

        String filename2 = filename.replace('\\', '/');
        //文件大小
        long fileSize = file.length();
        //文件名
        String fileName = filename2.substring(filename2.lastIndexOf("/")+1);

        //把文件名转化成字节数组存储
        byte[] fnBytes = fileName.getBytes();

        //文件名大小
        int fileNameSize = fnBytes.length;


        //创建bytes用于返回byte类型数组
        byte[] bytes = new byte[1+8+fileNameSize+8];

        //第一位放1，代表是文件
        bytes[0] = 1;
        //申请8个长度byte数组，把文件名大小转成bytes数组存储
        byte[] fnSizeBytes = ByteBuffer.allocate(8).putLong(fileNameSize).array();
        //申请8个长度的byte数组，把文件大小转成byte数组存储
        byte[] fsBytes = ByteBuffer.allocate(8).putLong(fileSize).array();

        //组织文件header
        //文件名大小
        System.arraycopy(fnSizeBytes,0,bytes,1,8);
        //文件名
        System.arraycopy(fnBytes,0,bytes,9,fnBytes.length);
        //文件大小
        System.arraycopy(fsBytes,0,bytes,9+fnBytes.length,8);
        return bytes;
    }

    /**
     * 解析文件包头
     * @param bytes 文件包头byte数据
     * @return String[0] -  文件名
     *         String[1] -  文件大小
     */
    @Nullable
    public static String[] unpackFile(@NotNull byte[] bytes){
        if(bytes.length < 17 || bytes[0] != 1){
            return null;//文件包头大小必须大于17个长度

        }
        // 1 + 8(文件名大小) + n(文件名) + 8(文件大小)
        //文件名大小
        long fnSize = ByteBuffer.wrap(bytes, 1, 8).getLong();
        //文件名
        byte[] fnBytes = new byte[(int)fnSize];
        System.arraycopy(bytes,9,fnBytes,0,(int)fnSize);
        //文件大小
        long fileSize = ByteBuffer.wrap(bytes,9+(int)fnSize,8).getLong();

        //创建返回String数组
        String[] header = new String[2];
        header[0] = new String(fnBytes);    //文件名
        header[1] = String.valueOf(fileSize); //文件大小
        return header;
    }

    /**
     * 获取包的大小
     * @param bytes 包头
     */
    public static long getPackSize(byte[] bytes){
        if(bytes.length != 9){
            return 0;
        }else{
            return ByteBuffer.wrap(bytes,1,8).getLong();
        }
    }

    public static void main(String[] args) {
        String str = "你好";
        byte[] pack = pack(str);
        //System.out.println(Arrays.toString(pack));

        System.out.println("-----------------");
        String str2 = unpack(pack);
        System.out.println(str2);

        System.out.println("--------------");
        byte[] fileBytes = packFile("file:G:/LADOU/预科班/模块四/新建文件夹/WeChatReadWriteProtocol.java");

        System.out.println(Arrays.toString(fileBytes));

        String[] strings = unpackFile(fileBytes);
        String str3 = strings[0];
        System.out.println("文件名是 " + str3);
        long size = Long.parseLong(strings[1]);
        System.out.println("文件大小是: " + size);

        //ByteOrder byteOrder = ByteOrder.nativeOrder();
        //System.out.println(byteOrder); //LITTLE_ENDIAN 该机器是小端字节序
    }
}
